package com.qf.fmw.Servlet;


import com.qf.fmw.DB.UserDB;
import com.qf.fmw.entity.User;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;


import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.IOUtils;


@WebServlet("/UserServlet")
public class UserServlet extends BaseServlet {

    //5.上传完整的表单数据
    private void upload5(HttpServletRequest request, HttpServletResponse response) throws FileUploadException, IOException, InvocationTargetException, IllegalAccessException, ServletException, FileUploadException {
        //1.创建一个磁盘工厂对象

        DiskFileItemFactory factory = new DiskFileItemFactory();
        //2.实例化上传对象，通过构造方法传递磁盘工厂对象
        ServletFileUpload upload = new ServletFileUpload(factory);
        //3.通过上传对象解析请求中的二进制数据
        List<FileItem> list = upload.parseRequest(request);
        User user = new User();
        HashMap<String, String> map = new HashMap<>();
        //4.遍历集合
        for (FileItem fileItem:list) {
            //判断是否为二进制文件
            if(!fileItem.isFormField()){
                //5.获取输入流对象
                InputStream is = fileItem.getInputStream();
                //6.获取文件存放的目录
                String path = getServletContext().getRealPath("upload");

                //使用时间当目录
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy//MM//dd//HH//mm//ss");
                String str = sdf.format(new Date());

                File file = new File(path, str);
                if(!file.exists()){
                    file.mkdirs();
                }

                //使用 UUID 生产文件名
                String fileName = fileItem.getName();
                UUID uuid = UUID.randomUUID();
                //fileName.substring(fileName.lastIndexOf(".")) --  获取源文件的后缀名
                fileName = uuid.toString()+fileName.substring(fileName.lastIndexOf("."));

                //7.创建目的源的抽象对象
                file = new File(file, fileName);

                //9.创建输出流对象
                FileOutputStream fos = new FileOutputStream(file);
                //10.拷贝
                byte[] b = new byte[1024];
                int len;
                while((len = is.read(b)) != -1){
                    fos.write(b,0,len);
                }
                fos.close();
                is.close();
                //把图片的相对路径存放到对象的属性中
                user.setImgUrl("upload//"+str+"//"+fileName);
            }else{//针对表单文本数据
                //String username = request.getParameter("username");
                //把表单的数据存放到 map 集合中
                String key = fileItem.getFieldName();
                String value = fileItem.getString("utf-8");
                if(map.containsKey(key)){
                    //存在多个相同的 name 属性时，把 value 进行拼接
                    map.put(key,map.get(key)+","+value);
                }else{
                    map.put(key,value);
                }

            }
        }
        //把 map 集合中的数据转换到 user 对象中，前提条件是 map 中的 key 跟 user 对象的属性一致时， value 赋值给对应的属性
        BeanUtils.populate(user,map);

        request.setAttribute("user",user);
        request.getRequestDispatcher("update.jsp").forward(request,response);
    }










    //添加用户功能
    protected void addUser(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //2.获取请求的数据
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        String sex = request.getParameter("sex");
        //String hobbies = request.getParameter("hobbies");
        String[] hobbies = request.getParameterValues("hobbies");
        String nativePlace = request.getParameter("nativePlace");
        //3.校验用户名是否重复
        for (User user : UserDB.list) {
            if (user.getUsername().equalsIgnoreCase(username)) {
//              response.getWriter().write("用户名重复，请回到注册页面重新输入");
                request.setAttribute("msg", "用户名重复，请回到添加页面重新输入");
                request.setAttribute("username", username);
                request.setAttribute("password", password);
                request.setAttribute("sex", sex);
                //将字符串转化为数组
                request.setAttribute("hobbies", Arrays.toString(hobbies));
                request.setAttribute("nativePlace", nativePlace);
                //页面跳转
                request.getRequestDispatcher("register.jsp").forward(request, response);
                return;
            }
        }
        //4.存放用户数据到数据库
        UserDB.list.add(new User(username, password, sex, hobbies, nativePlace));

        //5.响应前端
//        response.getWriter().write("<script>alert('添加成功');location.href='login.html'</script>");
        //页面跳转,重定向
//        response.sendRedirect("login.jsp");
        response.getWriter().write("<script>alert('添加成功');location.href='UserServlet?type=getList'</script>");
    }

    //编辑功能
    protected void Editor(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.获取请求中的数据 --要被编辑的用户id
        int id = Integer.parseInt(request.getParameter("id"));
        String username = request.getParameter("username");
        String sex = request.getParameter("sex");
        String hobbiesStr= request.getParameter("hobbiesStr");
        String nativePlace = request.getParameter("nativePlace");
        //3.在数据库中找到用户对象并删除
        User user = null;
        for (User u : UserDB.list) {
            if (u.getId() == id) {
                user = u;
            }
        }
        user.setUsername(username);
        user.setSex(sex);
        user.setHobbiesStr(hobbiesStr);
        user.setNativePlace(nativePlace);
        //响应前端
        response.getWriter().write("<script> alert('编辑成功');location.href='UserServlet?type=getList'</script>");
    }




    //批量删除
    protected void deleteChecked(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.获取请求中的数据    --  要被删除的用户 id 数组
        String[] idsStr = request.getParameterValues("id");
        //转换字符串数组为 int 类型数组
        int[] ids = Arrays.asList(idsStr).stream().mapToInt(Integer::parseInt).toArray();
        //2.遍历数组，逐个删除数据库中的对象
        for (int i = 0; i < ids.length; i++) {
            for (User user:UserDB.list) {
                if(user.getId() == ids[i]){
                    UserDB.list.remove(user);
                    break;
                }
            }
        }
        //响应前端
        response.getWriter().write("<script>alert('删除成功！');location.href='UserServlet?type=getList'</script>");
    }

    //搜索
    protected void search(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取请求中的数据
        String inputSelect = request.getParameter("inputSelect");
        String option = request.getParameter("option");

        List<User> list = new CopyOnWriteArrayList<>();
        switch (option) {
            case "用户名":
                for (User user : UserDB.list) {
                    if (user.getUsername().contains(inputSelect)) {
                        list.add(user);
                    }
                }
                break;
            case "性别":
                for (User user : UserDB.list) {
                    if (user.getSex().contains(inputSelect)) {
                        list.add(user);
                    }
                }
                break;
            case "爱好":
                for (User user : UserDB.list) {
                    if (user.getHobbiesStr().contains(inputSelect)) {
                        list.add(user);
                    }
                }
                break;
            case "籍贯":
                for (User user : UserDB.list) {
                    if (user.getNativePlace().equals(inputSelect)) {
                        list.add(user);
                    }
                }
                break;
        }
        //响应前端
        request.setAttribute("list", list);
        request.getRequestDispatcher("userList.jsp").forward(request, response);
    }

    //删除用户
    protected void delete(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取要删除的用户 id
        int id = Integer.parseInt(request.getParameter("id"));

        //遍历数据库删除对应的用户
        for (User user : UserDB.list) {
            if (user.getId() == id) {
                UserDB.list.remove(user);
                break;
            }
        }

        //响应前端，并提示删除成功，转发
        response.getWriter().write("<script>alert('删除成功');location.href='UserServlet?type=getList'</script>");
    }

    //展示所有用户信息
    protected void getList(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //从 session 中获取当前登录用户的 id
        int id = (int) request.getSession().getAttribute("id");
        //创建新的集合存放其他用户对象
        List<User> list = new CopyOnWriteArrayList<>(UserDB.list);
        //遍历
        for (User user : list) {
            if (id == user.getId()) {
                //删除当前登录用户
                list.remove(user);
                break;
            }
        }
        //将集合存入 request 域中
        request.setAttribute("list", list);
        //转发到 userList.jsp 页面
        request.getRequestDispatcher("userList.jsp").forward(request, response);
    }

    //修改个人信息
    protected void updateInit(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.获取 session 中登录用户的 id
        int id = (int) request.getSession().getAttribute("id");

        //2.根据 id 获取数据库中的用户对象
        User user = null;
        for (User u : UserDB.list) {
            if (u.getId() == id) {
                user = u;
                break;
            }
        }

        //3.把用户对象存储在请求作用域中
        user.setHobbiesStr(Arrays.toString(user.getHobbies()));
        request.setAttribute("user", user);
        request.getRequestDispatcher("update.jsp").forward(request, response);
    }

    //修改界面
    protected void update(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        /*
            校验用户名是否重复，重复则提示并返回填写数据(修改 User 类的结构)，
            不重复则根据 id 修改数据库中的数据，最后提示用户修改成功并退出登录
        */

        //获取前端发送的数据
        int id = Integer.parseInt(request.getParameter("id"));
        String username = request.getParameter("username");
        String sex = request.getParameter("sex");
        String[] hobbies = request.getParameterValues("hobbies");
        String nativePlace = request.getParameter("nativePlace");

        //判断是否重名
        User user = checkUsername(username);
        if (user != null && user.getId() != id) {
            request.setAttribute("error", "用户名已存在");
            //把用户对象存储在请求作用域中
            user.setHobbiesStr(Arrays.toString(user.getHobbies()));
            request.setAttribute("user", user);
            //转发到修改页面
            request.getRequestDispatcher("update.jsp").forward(request, response);
        }
        //修改用户信息
        for (User u : UserDB.list) {
            if (u.getId() == id) {
                user = u;
                break;
            }
        }
        user.setUsername(username);
        user.setSex(sex);
        user.setHobbies(hobbies);
        user.setNativePlace(nativePlace);

        //响应前端,提示用户修改成功并退出登录
        response.getWriter().write("<script>alert('修改成功');location.href='UserServlet?type=logout'</script>");
    }

    //退出登录
    private void logout(HttpServletRequest request, HttpServletResponse response) throws IOException {
        //1.清除 session 中存放的用户 id
        request.getSession().removeAttribute("id");

        //2.跳转到登录页面
        response.sendRedirect("login.jsp");
    }

    // 修改密码
    private void rePassword(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
        //1.获取前端发送的数据
        String oldPassword = request.getParameter("oldPassword");
        String newPassword = request.getParameter("newPassword");


        //2.获取 session 中登录用户的 id ，找到数据库中登录的用户对象
        int id = (int) request.getSession().getAttribute("id");
        User user = null;
        for (User u : UserDB.list) {
            if (u.getId() == id) {
                user = u;
                break;
            }
        }


        //4.修改数据库中的原密码
        user.setPassword(newPassword);

        //5.退出登录并返回登录页面
        response.getWriter().write("<script>alert('修改成功');location.href='UserServlet?type=logout'</script>");

    }

    //登录
    protected void login(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.获取验证码并校验
        //用户输入的验证
        String code = request.getParameter("code");
        String serverCode = (String) request.getSession().getAttribute("serverCode");
        if (!serverCode.equals(code)) {
            request.setAttribute("msg", "验证码错误");
            request.getRequestDispatcher("login.jsp").forward(request, response);
            return;
        }

        //2.获取请求发送的数据
        String username = request.getParameter("username");
        String password = request.getParameter("password");

        //3.校验用户名，遍历数据库查询用户名是否存在，存在则记录用户对象给 user 对象
        User user = checkUsername(username);
        //判断user对象是否为null，为null代表用户名不存在
        if (user == null) {
            //response.getWriter().write("<script>alert('用户名不存在');location.href='login.html'</script>");
            request.setAttribute("msg", "用户名不存在");
            request.setAttribute("username", username);
            request.setAttribute("password", password);

            //转发到登录页面
            request.getRequestDispatcher("login.jsp").forward(request, response);
            return;
        }
        //校验密码
        if (!user.getPassword().equals(password)) {
            //response.getWriter().write("<script>alert('密码错误');location.href='login.html'</script>");
            request.setAttribute("msg", "密码错误");
            request.setAttribute("username", username);
            request.setAttribute("password", password);

            //转发到登录页面
            request.getRequestDispatcher("login.jsp").forward(request, response);
            return;
        }

        String remember = request.getParameter("remember");
        if (remember != null) {
            Cookie cookie1 = new Cookie("username", username);
            cookie1.setMaxAge(60 * 60);
            Cookie cookie2 = new Cookie("password", password);
            cookie2.setMaxAge(60 * 60);
            response.addCookie(cookie1);
            response.addCookie(cookie2);
        }


        //登录成功响应前端
        //存放登录用户的 id 到 session 中
        request.getSession().setAttribute("id", user.getId());
        //重定向
        response.sendRedirect("index.jsp");
    }

    //校验用户名，遍历数据库查询用户名是否存在，存在则记录用户对象给 user 对象
    private User checkUsername(String username) {
        User user = null;
        for (User u : UserDB.list) {
            if (u.getUsername().equals(username)) {
                user = u;
                break;
            }
        }
        return user;
    }

    //注册
    protected void register(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取请求的数据
        //2.获取请求的数据
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        String sex = request.getParameter("sex");
        String[] hobbies = request.getParameterValues("hobbies");
        String nativePlace = request.getParameter("nativePlace");

        //3.校验用户名是否重复
        for (User user : UserDB.list) {
            if (user.getUsername().equalsIgnoreCase(username)) {
                request.setAttribute("msg", "用户名重复");
                request.setAttribute("username", username);
                request.setAttribute("password", password);
                request.setAttribute("sex", sex);
                //先把数组转换成字符串
                request.setAttribute("hobbies", Arrays.toString(hobbies));
                request.setAttribute("nativePlace", nativePlace);
                //页面跳转  --  转发
                request.getRequestDispatcher("register.jsp").forward(request, response);
                return;
            }
        }

        //4.存放用户数据到数据库
        UserDB.list.add(new User(username, password, sex, hobbies, nativePlace));

        //5.响应前端
        response.sendRedirect("login.jsp");
    }
}

